
#ifndef WIN_TCP_CLIENT_ZSLOG_H
#define WIN_TCP_CLIENT_ZSLOG_H

#include <string>
#include <functional>

#include "Poco/Logger.h"
#include "Poco/LogStream.h"
#include "Poco/Message.h"
#include "Poco/FileChannel.h"
#include "Poco/ConsoleChannel.h"
#include "Poco/PatternFormatter.h"
#include "Poco/FormattingChannel.h"

using Poco::Logger;
using Poco::LogStream;
using Poco::Message;
using Poco::FileChannel;
using Poco::ConsoleChannel;
using Poco::PatternFormatter;
using Poco::FormattingChannel;

namespace zs
{
    void SetLogPath(const std::string &path);
}

class BaseName
{
public:
    template<int N>
    BaseName(const char (&array)[N]) : basename_(array), len_(N - 1)
    {
        const char* ptr = ::strrchr(basename_, '\\');
        if (nullptr != ptr)
        {
            basename_ = ptr + 1;
            len_ -= static_cast<size_t>(basename_ - array);
        }
    }
public:
    const char* basename_{nullptr};
    int len_;
};

class LogOutPut
{
public:
    using LogOutFunc = std::function<void(const std::string& log)>;
public:
    LogOutPut(BaseName filename, int line);
    LogOutPut(BaseName filename, int line, const char* function_name);
    LogOutPut(BaseName filename, int line, int syserrno);
    void end_line();
    ~LogOutPut();
    LogStream& logStream() { return logStream_; };
public:
    static void set_log_out_func(LogOutFunc func);
    static void set_file_channel(FileChannel* fileChannel);
    static FileChannel* get_file_channel() { return FileChannel_;};
    static void set_console_channel(ConsoleChannel* consoleChannel);
    static ConsoleChannel* get_console_channel() { return ConsoleChannel_;};
    static void set_formatting_channel(FormattingChannel* formattingChannel);
    static FormattingChannel* get_formatting_channel() { return FormattingChannel_;};
private:
    //日志格式通道
    static FileChannel* FileChannel_;
    static ConsoleChannel* ConsoleChannel_;
    static FormattingChannel* FormattingChannel_;
    const char* logger = "ZsLog";
    LogStream logStream_{(Logger::get(logger))};
};

#define LOG_TRACE if (LogOutPut::log_level() <= kLogLevel::LevelTrace) \
                     LogOutPut(__FILE__, __LINE__, kLogLevel::LevelTrace, __FUNCTION__).logStream().trace()

#define LOG_DEBUG if (LogOutPut::log_level() <= kLogLevel::LevelDebug) \
                    LogOutPut(__FILE__, __LINE__, kLogLevel::LevelDebug, __FUNCTION__).logStream().debug()

#define LOG_INFO LogOutPut(__FILE__, __LINE__).logStream().information()

#define LOG_WARN LogOutPut(__FILE__, __LINE__, kLogLevel::LevelWarn).logStream().warning()

#define LOG_ERROR LogOutPut(__FILE__, __LINE__).logStream().error()

#define LOG_FATAL LogOutPut(__FILE__, __LINE__, kLogLevel::LevelFatal).logStream().fatal()



#endif //WIN_TCP_CLIENT_ZSLOG_H
